#ifndef WIN_THREAD_H
#define WIN_THREAD_H
#include "config.h"

#include <windows.h>
#include <sys/timeb.h>
#include <process.h>

#include "aux_types.h"
#include "aux_errno.h"

typedef enum {
    MUTEX_STATE_UNINIT = 0,
    MUTEX_STATE_LOCK,
    MUTEX_STATE_UNLOCK,
    MUTEX_STATE_UNREACHABLE,
    MUTEX_STATE_MAX
}EMUTEX_STATE;



typedef struct {
    HANDLE       hMutex;
    EMUTEX_STATE eState;
} pthread_mutex_t;

//typedef HANDLE pthread_mutex_t;
typedef int    pthread_condattr_t;
typedef int    pthread_mutexattr_t;
typedef HANDLE pthread_t;
typedef DWORD  pthread_attr_t;

typedef void *(*pThreadFunc)(void*);

int pthread_create(pthread_t *tidp, const pthread_attr_t *attr,
    void *(*start_rtn)(void*), void *arg);

#define pthread_join(thr, statusp)                                             \
    ((WaitForSingleObject((thr), INFINITE) == WAIT_OBJECT_0) &&                \
    (((statusp) == NULL) ?                                                     \
      0 : (GetExitCodeThread((thr), (LPDWORD)(statusp)) ? 0 : -1)))

//#define PTHREAD_MUTEX_INITIALIZER not use

int pthread_mutex_lock(pthread_mutex_t *ptMutex);
int pthread_mutex_unlock(pthread_mutex_t *ptMutex);
int pthread_mutex_init(pthread_mutex_t *ptMutex, const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *ptMutex);


typedef struct timespec {
    s64 tv_sec;
    s64 tv_nsec;
} timespec;

typedef struct {
    /* number of waiting threads */
    int nCntOfThreadWaiting;

    /* serialize access to <nCntOfThreadWaiting>  */
    CRITICAL_SECTION lockForCntOfWaiting;

    /* waiting for the condition to become signaled. */
    HANDLE hSemephore;

    /*
     * an auto-reset event used by the broadcast/signal thread to wait
     * for all the waiting thread(s) to wake up and be released from the
     * semaphore.
     */
    HANDLE hEventAllWakeUpDone;

    /*
     * keeps track of whether we were broadcasting or signaling.  This
     * allows us to optimize the code if we're just signaling.
     */
    size_t bIsBroadcasting;
} pthread_cond_t;

u64 _pthread_time_in_ms(void);
u64 _pthread_time_in_ms_from_timespec(const struct timespec *ts);
u64 _pthread_rel_time_in_ms(const struct timespec *ts);
int pthread_cond_init(pthread_cond_t *p,const pthread_condattr_t * c);
int pthread_cond_destroy(pthread_cond_t *c);
int pthread_cond_signal(pthread_cond_t *c);
int pthread_cond_broadcast(pthread_cond_t *c);
int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *external);
int pthread_cond_timedwait(pthread_cond_t *ptCond,
                                           pthread_mutex_t *pExMutex,
                                           const struct timespec *abstime);


EErrNo xIPCChkPthreadMutexValid(const pthread_mutex_t *ptMutex);

#ifndef ETIMEDOUT
#define ETIMEDOUT 0x1
#endif

#ifndef EINVAL
#define EINVAL 22
#endif

#ifndef EAGAIN
#define EAGAIN 11
#endif

#ifndef ENOTRECOVERABLE
#define ENOTRECOVERABLE 131
#endif

#ifndef EFAULT
#define EFAULT 14
#endif

#ifndef EBUSY
#define EBUSY 16
#endif

#ifndef EPERM
#define EPERM 1
#endif

#endif

